# Copyright (c) 2025 Huawei Technologies Co., Ltd.
# openUBMC is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#         http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
import os

from conan import ConanFile
from conan.tools.scm import Git
from conan.tools.files import copy, chdir
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout, CMakeDeps

required_conan_version = ">=2.13.0"


class GrpcConan(ConanFile):
    name = "grpc"
    description = "Google's RPC library and framework"
    settings = "os", "compiler", "build_type", "arch"
    exports_sources = ["permissions.ini"]
    options = {
        "shared": [True, False],
        "fPIC": [True, False],
        "with_zlib": [True, False],
        "with_openssl": [True, False],
        "with_cares": [True, False],
        "with_abseil": [True, False],
        "build_codegen": [True, False]
    }
    default_options = {
        "shared": True,
        "fPIC": True,
        "with_zlib": False,
        "with_openssl": False,
        "with_cares": True,
        "with_abseil": True,
        "build_codegen": True
    }
    generators = "CMakeDeps"
    _cmake = None

    def layout(self):
        cmake_layout(self)

    def source(self):
        source = self.conan_data["sources"][self.version]
        git = Git(self)
        git.fetch_commit(url=source["url"], commit=source["branch"])
    
    def requirements(self):
        requires = self.conan_data.get("requires", {}).get(self.version, [])
        for req in requires:
            self.requires(req)

    def build_requirements(self):
        if os.path.exists('/home/bin/protoc') and os.path.exists('/home/bin/grpc_cpp_plugin'):
            return
        requires = self.conan_data.get("tool_requires", {}).get(self.version,[])
        for req in requires:
            self.tool_requires(req)
    
    def generate(self):
        tc = CMakeToolchain(self)
        
        # 添加编译标志
        tc.extra_cflags = ["-w"]
        tc.extra_cxxflags = ["-w"]

        absl_rootpath = self.dependencies["abseil"].package_folder
        protobuf_rootpath = self.dependencies["protobuf"].package_folder
        cares_rootpath = self.dependencies["c_ares"].package_folder
        if os.path.exists('/home/bin/protoc') and os.path.exists('/home/bin/grpc_cpp_plugin'):
            lib_path = '/home/lib'
            os.environ['LD_LIBRARY_PATH'] = f'{lib_path}:{os.environ.get('LD_LIBRARY_PATH', '')}'
            tc.variables['_gRPC_PROTOBUF_PROTOC_EXECUTABLE'] = '/home/bin/protoc'
            tc.variables['CMAKE_PROGRAM_PATH'] = '/home/bin/'
        else:
            lib_path = os.path.join(self.dependencies.build['protobuf'].package_folder, 'lib')
            os.environ['LD_LIBRARY_PATH'] = f'{lib_path}:{os.environ.get('LD_LIBRARY_PATH', '')}'
            protoc_path = os.path.join(self.dependencies.build['protobuf'].package_folder, 'bin/protoc')
            tc.variables['_gRPC_PROTOBUF_PROTOC_EXECUTABLE'] = protoc_path
        re2_rootpath = self.dependencies["re2"].package_folder
        absl_dir = os.path.join(absl_rootpath, "lib", "cmake", "absl")
        re2_dir = os.path.join(re2_rootpath, "lib", "cmake", "re2")
        protobuf_dir = ""
        if self.settings.arch == "x86_64":
            protobuf_dir = os.path.join(protobuf_rootpath, "lib")
        else:
            protobuf_dir = os.path.join(protobuf_rootpath, "usr", "lib64")
        tc.variables["gRPC_INSTALL"] = True
        tc.variables["gRPC_BUILD_TEST"] = False
        tc.variables["gRPC_BUILD_CSHARP_EXT"] = False
        tc.variables["gRPC_ZLIB_PROVIDER"] = "package"
        tc.variables["gRPC_SSL_PROVIDER"] = "package"
        tc.variables["gRPC_CARES_PROVIDER"] = "package"
        tc.variables["gRPC_ABSL_PROVIDER"] = "package"
        tc.variables["gRPC_RE2_PROVIDER"] = "package"
        tc.variables["gRPC_PROTOBUF_PROVIDER"] = "package"
        tc.variables["CMAKE_CXX_STANDARD"] = 17
        tc.variables["CMAKE_PREFIX_PATH"] = (
            f"{protobuf_rootpath};{re2_dir};{cares_rootpath};{absl_dir};"
        )
        tc.variables["CMAKE_PREFIX_PATH"] += protobuf_dir

        tc.generate()

    def build(self):
        with chdir(self, self.source_folder):
            if not self.settings.arch == "x86_64":
                self.run(
                    'sed -i \'s/set(gRPC_INSTALL_LIBDIR "lib"/set(gRPC_INSTALL_LIBDIR "usr\/lib64"/\' CMakeLists.txt')
        cmake = self._configure_cmake()
        cmake.build()

    def package_info(self):
        self.cpp_info.libdirs = ["lib", "usr/lib64"]

    def package(self):
        cmake = self._configure_cmake()
        cmake.install()
        copy(self, "permissions.ini", src=self.export_sources_folder,
            dst=self.package_folder)
        if self.settings.arch == "x86_64":
            return
        libdir = os.path.join(self.package_folder, "usr/lib64")
        if self.settings.arch == "armv8":
            strip_tool = "aarch64-target-linux-gnu-strip"
        elif self.settings.arch == "x86_64":
            strip_tool = "strip"
        else:
            strip_tool = "strip"
        for file in os.listdir(libdir):
            if not file.endswith(".a"):
                continue
            file_path = os.path.join(libdir, file)
            self.run(f"{strip_tool} -d {file_path}")

    def _configure_cmake(self):
        if self._cmake:
            return self._cmake
        self._cmake = CMake(self)
        self._cmake.configure(cli_args=["--no-warn-unused-cli"])
        return self._cmake